// 版权所有2009 Go作者。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// 包adler32实现Adler-32校验和。
// 
// 在RFC 1950中定义：
// Adler-32由每个字节累积的两个和组成：s1是
// 所有字节的和，s2是所有s1值的和。两个和
// 都是模65521。s1初始化为1，s2初始化为0。
// Adler-32校验和按most-
// 有效字节第一（网络）顺序存储为s2*65536+s1。
package adler32

import (
	"errors"
	"hash"
)

const (
	// mod是小于65536的最大素数。
	mod = 65521
	// nmax是最大的n，因此
	// 255*n*（n+1）/2+（n+1）*（mod-1）<=2^32-1。
	// RFC1950中提到了它（搜索“5552”）。
	nmax = 5552
)

// Adler-32校验和的大小，以字节为单位。
const Size = 4

// 摘要表示校验和的部分计算。
// 低16位为s1，高16位为s2。
type digest uint32

func (d *digest) Reset() { *d = 1 }

// New返回一个新的hash.Hash32计算Adler-32校验和。它的
// Sum方法将以大端字节顺序排列值。
// 返回的Hash32还实现encoding.BinaryMarshaler和
// encoding.BinaryUnmarshaler来封送和解封哈希的内部
// 状态。
func New() hash.Hash32 {
	d := new(digest)
	d.Reset()
	return d
}

func (d *digest) Size() int { return Size }

func (d *digest) BlockSize() int { return 4 }

const (
	magic         = "adl\x01"
	marshaledSize = len(magic) + 4
)

func (d *digest) MarshalBinary() ([]byte, error) {
	b := make([]byte, 0, marshaledSize)
	b = append(b, magic...)
	b = appendUint32(b, uint32(*d))
	return b, nil
}

func (d *digest) UnmarshalBinary(b []byte) error {
	if len(b) < len(magic) || string(b[:len(magic)]) != magic {
		return errors.New("hash/adler32: invalid hash state identifier")
	}
	if len(b) != marshaledSize {
		return errors.New("hash/adler32: invalid hash state size")
	}
	*d = digest(readUint32(b[len(magic):]))
	return nil
}

func appendUint32(b []byte, x uint32) []byte {
	a := [4]byte{
		byte(x >> 24),
		byte(x >> 16),
		byte(x >> 8),
		byte(x),
	}
	return append(b, a[:]...)
}

func readUint32(b []byte) uint32 {
	_ = b[3]
	return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
}

// 将p添加到运行校验和d中。
func update(d digest, p []byte) digest {
	s1, s2 := uint32(d&0xffff), uint32(d>>16)
	for len(p) > 0 {
		var q []byte
		if len(p) > nmax {
			p, q = p[:nmax], p[nmax:]
		}
		for len(p) >= 4 {
			s1 += uint32(p[0])
			s2 += s1
			s1 += uint32(p[1])
			s2 += s1
			s1 += uint32(p[2])
			s2 += s1
			s1 += uint32(p[3])
			s2 += s1
			p = p[4:]
		}
		for _, x := range p {
			s1 += uint32(x)
			s2 += s1
		}
		s1 %= mod
		s2 %= mod
		p = q
	}
	return digest(s2<<16 | s1)
}

func (d *digest) Write(p []byte) (nn int, err error) {
	*d = update(*d, p)
	return len(p), nil
}

func (d *digest) Sum32() uint32 { return uint32(*d) }

func (d *digest) Sum(in []byte) []byte {
	s := uint32(*d)
	return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s))
}

// 校验和返回数据的Adler-32校验和。
func Checksum(data []byte) uint32 { return uint32(update(1, data)) }
